
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import List, Optional
import sqlite3
import json
import os

app = FastAPI(title="原料药变更决策后台", version="0.1.0")

# CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 数据库初始化
DB_FILE = "decision.db"

def init_db():
    conn = sqlite3.connect(DB_FILE)
    cur = conn.cursor()
    cur.execute("""
        CREATE TABLE IF NOT EXISTS nodes (
            id TEXT PRIMARY KEY,
            label TEXT NOT NULL,
            node_type TEXT NOT NULL,
            category TEXT,
            regulation TEXT,
            materials TEXT,
            next_nodes TEXT
        )
    """)
    # 首次写入示例节点（与 Mermaid 图对应）
    sample = [
        ("A", "原料药变更", "start", "", "", "", "B"),
        ("B", "变更类型？", "decision", "", "", "", "C,K,P,T,Y,AH"),
        ("C", "生产工艺变更", "process", "", "", "", "C1"),
        ("C1", "质量一致性？", "decision", "", "", "", "D,E"),
        ("D", "微小变更（年报）", "end", "微小", "《办法》第X条", "1.变更说明 2.质量对比", ""),
        ("E", "制剂质量一致性？", "decision", "", "", "", "F,G"),
        ("F", "中等变更（备案）", "end", "中等", "《办法》第Y条", "1.备案表 2.检验报告", ""),
        ("G", "重大变更（补充申请）", "process", "", "", "", "H"),
        ("H", "是否需生物等效性研究？", "decision", "", "", "", "I,J"),
        ("I", "补充申请+BE数据", "end", "重大", "《办法》第Z条", "1.补充申请表 2.BE报告", ""),
        ("J", "论证+补充申请", "end", "重大", "《办法》第Z条", "1.论证资料 2.补充申请", ""),
        ("K", "生产场地/批量变更", "process", "", "", "", "K1"),
        ("K1", "质量一致性？", "decision", "", "", "", "L,M"),
        ("L", "年报", "end", "微小", "", "年报资料", ""),
        ("M", "是否关联其他变更？", "decision", "", "", "", "N,O"),
        ("N", "年报", "end", "微小", "", "年报资料", ""),
        ("O", "按生产工艺变更处理", "process", "", "", "", "C"),
        ("P", "注册标准变更", "process", "", "", "", "P1"),
        ("P1", "是否影响制剂内控标准？", "decision", "", "", "", "Q,R,S"),
        ("Q", "微小变更（年报）", "end", "微小", "", "年报资料", ""),
        ("R", "中等变更（备案）", "end", "中等", "《办法》第Y条", "备案资料", ""),
        ("S", "按指导原则\"八\"处理", "process", "", "", "", ""),
        ("T", "贮藏条件/有效期变更", "process", "", "", "", "T1"),
        ("T1", "是否因质量问题变更？", "decision", "", "", "", "U,W"),
        ("U", "是否需稳定性评估？", "decision", "", "", "", "V,W"),
        ("V", "备案/补充申请", "end", "中等/重大", "", "稳定性资料", ""),
        ("W", "年报", "end", "微小", "", "年报资料", ""),
        ("X", "年报", "end", "微小", "", "年报资料", ""),
        ("Y", "供应商变更", "process", "", "", "", "Y1"),
        ("Y1", "质量一致性？", "decision", "", "", "", "Z,AE"),
        ("Z", "制剂质量一致性？", "decision", "", "", "", "AA,AB"),
        ("AA", "中等变更（备案）", "end", "中等", "", "备案资料", ""),
        ("AB", "是否需3批制剂检验？", "decision", "", "", "", "AC,AD"),
        ("AC", "中等变更（备案）", "end", "中等", "", "备案+3批检验", ""),
        ("AD", "重大变更（补充申请）", "end", "重大", "", "补充申请资料", ""),
        ("AE", "制剂质量一致性？", "decision", "", "", "", "AF,AG"),
        ("AF", "中等变更（备案）", "end", "中等", "", "备案资料", ""),
        ("AG", "重大变更（补充申请）", "end", "重大", "", "补充申请资料", ""),
        ("AH", "未登记原料药", "tip", "", "", "", ""),
    ]
    cur.executemany("REPLACE INTO nodes VALUES(?,?,?,?,?,?,?)", sample)
    conn.commit()
    conn.close()

init_db()

# 模型
class NodeOut(BaseModel):
    id: str
    label: str
    node_type: str
    category: Optional[str] = None
    regulation: Optional[str] = None
    materials: Optional[str] = None
    next_nodes: Optional[str] = None

class DecisionPathIn(BaseModel):
    node_ids: List[str]

# 接口
@app.get("/api/nodes", response_model=List[NodeOut])
def list_nodes():
    conn = sqlite3.connect(DB_FILE)
    conn.row_factory = sqlite3.Row
    rows = conn.execute("SELECT * FROM nodes").fetchall()
    conn.close()
    return [NodeOut(**dict(r)) for r in rows]

@app.get("/api/nodes/{node_id}", response_model=NodeOut)
def get_node(node_id: str):
    conn = sqlite3.connect(DB_FILE)
    conn.row_factory = sqlite3.Row
    row = conn.execute("SELECT * FROM nodes WHERE id=?", (node_id,)).fetchone()
    conn.close()
    if not row:
        raise HTTPException(status_code=404, detail="Node not found")
    return NodeOut(**dict(row))

@app.post("/api/decision/report")
def gen_report(payload: DecisionPathIn):
    # TODO: 拼接节点详情，生成 PDF
    return {"pdf_url": "/static/report_placeholder.pdf"}

# 静态文件
from fastapi.staticfiles import StaticFiles
os.makedirs("static", exist_ok=True)
app.mount("/static", StaticFiles(directory="static"), name="static")

if __name__ == "__main__":
    import uvicorn
    uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
